package thread.juc.lock;

import lombok.Data;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;

/**
 * 生产者消费者案例:
 * befor:           生产者A:1   after     生产者A:1
 * 生产者A:2             生产者A:2
 * 生产者A:3             生产者A:3
 * 生产者A:4             生产者A:4
 * 生产者A:5             生产者A:5
 * 生产者A:6             生产者A:6
 * 消费者B:5             生产者A:7
 * 消费者B:4             生产者A:8
 * 消费者B:3             生产者A:9
 * 消费者B:2             生产者A:1
 * 消费者B:1             产品已满!
 * 消费者B:0             消费者B:9
 * 缺货了!               消费者B:8
 * 缺货了!               消费者B:7
 * 缺货了!               消费者B:6
 * 缺货了!               消费者B:5
 * 缺货了!               消费者B:4
 * 缺货了!               消费者B:3
 * 缺货了!               消费者B:2
 * 缺货了!               消费者B:1
 * 缺货了!               消费者B:0
 * 缺货了!               缺货了!
 * 缺货了!               生产者A:1
 * 缺货了!               生产者A:2
 * 缺货了!               生产者A:3
 * 缺货了!               生产者A:4
 * 生产者A:1             生产者A:5
 * 生产者A:2             生产者A:6
 * 生产者A:3             生产者A:7
 * 生产者A:4             生产者A:8
 * 生产者A:5             生产者A:9
 * 生产者A:6             消费者B:8
 * 生产者A:7             消费者B:7
 * 生产者A:8             消费者B:6
 * 生产者A:9             消费者B:5
 * 生产者A:10            消费者B:4
 * 产品已满!             消费者B:3
 * 产品已满!             消费者B:2
 * 产品已满!             消费者B:1
 * 产品已满!             消费者B:0
 * <p>
 * 消费者和生产速度不一样，导致缺货或商品过多情况！
 */
public class ProductAndConsumer {
    public static void main(String[] args) {
        Clerk clerk = new Clerk();
        Productor productor = new Productor(clerk);
        Consumer consumer = new Consumer(clerk);
        new Thread(productor, "生产者A").start();
        new Thread(consumer, "消费者B").start();
        new Thread(productor, "生产者C").start();
        new Thread(consumer, "消费者D").start();
    }
}

class Productor implements Runnable {
    private Clerk clerk;

    public Productor(Clerk clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            clerk.get();
        }
    }
}

class Consumer implements Runnable {
    @NonNull
    private Clerk clerk;

    public Consumer(Clerk clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            clerk.sale();
        }
    }
}

//店员
class Clerk {
    private int product = 0;

    //进货
    public synchronized void get() {
//        if (product >= 1) {
        while (product >= 1) {
            System.out.println("产品已满!");
            try {
                this.wait();//不再生产
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
//        else {
        System.out.println(Thread.currentThread().getName() + ":" + ++product);
        this.notifyAll();//可以卖货
//        }

    }

    //卖货
    public synchronized void sale() {
        while (product <= 0) {//变成1 this.wait();就一直等待，所以去掉else 上面↑
            System.out.println("缺货了!");
            try {
                this.wait();//不许消费
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
//        else {
        System.out.println(Thread.currentThread().getName() + ":" + --product);
        this.notifyAll();//有空位,可以补货
//        }
    }
}
